package com.rt.easyjava.base.biz1.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.rt.easyjava.base.biz1.bean.TmptAuthDeptBiz;
import com.rt.easyjava.base.biz1.bean.TmptAuthUserA2roleListBiz;
import com.rt.easyjava.base.biz1.bean.TmptAuthUserBiz;
import com.rt.easyjava.base.biz1.bean.base.TmptAuthUserA2roleList;
import com.rt.easyjava.base.biz1.dto.TmptAuthDeptBizDto;
import com.rt.easyjava.base.biz1.dto.TmptAuthUserBizDto;
import com.rt.easyjava.base.biz1.dto.TmptAuthUserBizNoPsdDto;
import com.rt.easyjava.base.biz1.mapper.TmptAuthUserBizMapper;
import com.rt.easyjava.base.biz1.mapper.base.TmptAuthUserA2roleListMapper;
import com.rt.easyjava.base.biz1.service.impl.base.TmptAuthUserServiceImpl;
import com.rt.easyjava.base.biz1.service.intf.TmptAuthDeptBizService;
import com.rt.easyjava.base.biz1.service.intf.TmptAuthUserBizService;
import com.rt.easyjava.common.base.Result;
import com.rt.easyjava.common.config.dozer.MyMapper;
import com.rt.easyjava.common.enums.TmptAuthPosition;
import com.rt.easyjava.common.utils.others.StringUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

/**
 *  服务实现类
 * @author wuxiaoyong
 * @since 2020-06-13
 */
@Slf4j
@Service(value = "tmptAuthUserService")
@Transactional(propagation = Propagation.REQUIRED)
public class TmptAuthUserBizServiceImpl extends TmptAuthUserServiceImpl implements TmptAuthUserBizService{
    @Autowired
    private MyMapper mapper;
    @Resource
    private TmptAuthUserBizMapper tmptAuthUserBizMapper;
    @Resource
    private TmptAuthUserBizService tmptAuthUserBizService;
    @Resource
    private TmptAuthDeptBizService tmptAuthDeptBizService;
    @Resource
    private TmptAuthUserA2roleListMapper tmptAuthUserA2roleListMapper;

    @Autowired
    private PasswordEncoder passwordEncoder;
    @Autowired
    private TmptAuthUserPwdBizServiceImpl tmptAuthUserPwdBizService;

    @Override
    public void validatePassword(String loginname, String passwordInput, String passwordUser, String loginTimes) {
        int loginTimesInt = Integer.parseInt(loginTimes);
        // 验证登录次数，是否非法登录
        Integer loginTimesFromDb = selectByKey("loginname", loginname).getLogintimes();
        if (loginTimesFromDb.intValue()!=loginTimesInt){
            throw new RuntimeException("登录机密串版本不一致，请重新登录");
        }

        // 登录前验证
        {
            Result result = tmptAuthUserPwdBizService.validateBeforeLogin(loginname);
            if (!result.isSuccess()) {
                throw new RuntimeException(result.getContentOnly());
            }
        }

        //比较前端传入的密码明文和数据库中加密的密码是否相等
        if (!passwordEncoder.matches(passwordInput, passwordUser)) {
            // log: 密码不正确
            Result result = tmptAuthUserPwdBizService.changeUserInfoWhenPsdFailure(loginname);
            // 密码错误次数
            int loginTimeFailure = Integer.parseInt(result.getObj().toString());
            if (TmptAuthUserPwdBizServiceImpl._LoginTimesFailure-loginTimeFailure-1 == 0) {
                throw new RuntimeException("密码错误，账号已锁定，"+TmptAuthUserPwdBizServiceImpl._TimeOut_Minute+"分钟后自动解锁");
            }
            if (loginTimeFailure>=3) {
                throw new RuntimeException("密码错误，剩余"+(TmptAuthUserPwdBizServiceImpl._LoginTimesFailure-loginTimeFailure-1)+
                        "次机会");
            }
            // return
            throw new RuntimeException("密码错误");
        }

        // 登录成功，清除一些信息
        {
            Result result = tmptAuthUserPwdBizService.changeUserInfoWhenLoginSuc(loginname);
            if (!result.isSuccess()) {
                throw new RuntimeException("登录成功，清除一些信息失败");
            }
        }
    }

    @Override
    public void validatePasswordInnerService(String loginname, String passwordInput, String passwordUser, String loginTimes) {
        int loginTimesInt = Integer.parseInt(loginTimes);
        // 验证登录次数，是否非法登录
        Integer loginTimesFromDb = selectByKey("loginname", loginname).getLogintimes();
        if (loginTimesFromDb.intValue()!=loginTimesInt){
            throw new RuntimeException("登录机密串版本不一致，请重新登录");
        }

        // 登录前验证
        {
            Result result = tmptAuthUserPwdBizService.validateBeforeLogin(loginname);
            if (!result.isSuccess()) {
                throw new RuntimeException(result.getContentOnly());
            }
        }

        //比较前端传入的密码明文和数据库中加密的密码是否相等
        if (!passwordInput.equalsIgnoreCase(passwordUser)) {
            // log: 密码不正确
            Result result = tmptAuthUserPwdBizService.changeUserInfoWhenPsdFailure(loginname);
            // 密码错误次数
            int loginTimeFailure = Integer.parseInt(result.getObj().toString());
            if (TmptAuthUserPwdBizServiceImpl._LoginTimesFailure-loginTimeFailure-1 == 0) {
                throw new RuntimeException("密码错误，账号已锁定，"+TmptAuthUserPwdBizServiceImpl._TimeOut_Minute+"分钟后自动解锁");
            }
            if (loginTimeFailure>=3) {
                throw new RuntimeException("密码错误，剩余"+(TmptAuthUserPwdBizServiceImpl._LoginTimesFailure-loginTimeFailure-1)+
                        "次机会");
            }
            // return
            throw new RuntimeException("密码错误");
        }

        // 登录成功，清除一些信息
        {
            Result result = tmptAuthUserPwdBizService.changeUserInfoWhenLoginSuc(loginname);
            if (!result.isSuccess()) {
                throw new RuntimeException("登录成功，清除一些信息失败");
            }
        }
    }

    /**
     * select one by id
     * @param userId
     * @return
     */
    @Override
    @Deprecated
    public Result<TmptAuthUserBizDto> selectSubordinatesByUserId(Long userId) {
        List<TmptAuthUserBizNoPsdDto> subordinateDtoAllList = new ArrayList<>();

        TmptAuthUserBiz user = tmptAuthUserBizMapper.selectById(userId);

        // 找下级部门
        List<Long> subDeptIdList = new ArrayList<>();
        Long deptId = user.getTmptAuthDeptPostId();
        TmptAuthDeptBizDto deptBizDto = deptTree(deptId, subDeptIdList);
        // 下级部门
        System.out.println("subDeptIdList:"+subDeptIdList);

        // 我的直属下级
        Integer position = user.getTmptAuthPosition(); // 我的级别： 100大队长， 90中队长， 80小队长， 0队员
        /*if (TmptAuthPosition.Member.getId().equals(position)) {
            return Result.builder().success("我是成员，没有下属");
        }*/
        // 查询所属部门下所有员工
        Long deptPostId = user.getTmptAuthDeptPostId();
        if (StringUtils.isNull(deptPostId)) {
            return Result.builder().success("我的部门不见了");
        }

        QueryWrapper queryWrapper = new QueryWrapper();
        queryWrapper.eq("t1.tmpt_auth_dept_post_id", deptPostId);
        queryWrapper.lt("t1.tmpt_auth_position", position);
        queryWrapper.eq("t1.deleteflag", 0);
        List<TmptAuthUserBiz> subordinateList = tmptAuthUserBizMapper.myList(queryWrapper);

        List<TmptAuthUserBiz> subordinateList1 = new ArrayList<>();
        if (subDeptIdList.size()>0) {
            QueryWrapper queryWrapper1 = new QueryWrapper();
            queryWrapper1.in("t1.tmpt_auth_dept_post_id", subDeptIdList);
            queryWrapper1.eq("t1.deleteflag", 0);
            subordinateList1 = tmptAuthUserBizMapper.myList(queryWrapper1);
        }

        List<TmptAuthUserBiz> subordinateAllList = new ArrayList<>();
        subordinateAllList.addAll(subordinateList);
        subordinateAllList.addAll(subordinateList1);

        List<TmptAuthUserBizNoPsdDto> subordinateDtoList = mapper.maplist(subordinateAllList, TmptAuthUserBizNoPsdDto.class);

        return Result.builder(subordinateDtoList).success();
    }



    /**
     树结构查询方法，非树结构会造一个空方法备用着。
     */
    private TmptAuthDeptBizDto deptTree (Long deptId, List subDeptIdList) {
        // when id=0 , id=0 is parantId=0 , 默认设置一个空根
        TmptAuthDeptBizDto tmptAuthDeptBizDto = new TmptAuthDeptBizDto();
        tmptAuthDeptBizDto.setId(0L);
        if (deptId!=0) {
            TmptAuthDeptBiz tmptAuthDeptBiz = tmptAuthDeptBizService.getById(deptId);
            tmptAuthDeptBizDto = mapper.map(tmptAuthDeptBiz, TmptAuthDeptBizDto.class);
        }
        deptTreeReduce(tmptAuthDeptBizDto, subDeptIdList);

        return tmptAuthDeptBizDto;
    }

    private void deptTreeReduce(TmptAuthDeptBizDto tmptAuthDeptBizDto, List subDeptIdList){
        // myson list
        QueryWrapper<TmptAuthDeptBiz> queryWrapper=new QueryWrapper<>();
        // queryWrapper.eq("tmpt_auth_dept_id", tmptAuthDeptBizDto.getId());
        queryWrapper.eq("parent_id", tmptAuthDeptBizDto.getId());
        queryWrapper.eq("deleteflag", 0);
        queryWrapper.orderByAsc(true, "id");
        List<TmptAuthDeptBiz> sonList = tmptAuthDeptBizService.list(queryWrapper);
        if (sonList.size() == 0) {
            return;
        }
        List<TmptAuthDeptBizDto> sonDtoList = mapper.maplist(sonList, TmptAuthDeptBizDto.class);

        tmptAuthDeptBizDto.setTmptAuthDeptList(sonDtoList);
        for (TmptAuthDeptBizDto dto : sonDtoList) {
            subDeptIdList.add(dto.getId());
            deptTreeReduce(dto, subDeptIdList);
        }
    }


    /**
     * select one by id
     * @param userId
     * @return
     */
    //@Override
    public Result<TmptAuthUserBizDto> selectSubordinatesCurDeptByUserId(Long userId) {
        TmptAuthUserBiz user = tmptAuthUserBizMapper.selectById(userId);
        Integer position = user.getTmptAuthPosition(); // 我的级别： 100大队长， 90中队长， 80小队长， 0队员
        if (TmptAuthPosition.Member.getId().equals(position)) {
            return Result.builder().success("我是成员，没有下属");
        }
        // 查询所属部门下所有员工
        Long deptPostId = user.getTmptAuthDeptPostId();
        if (StringUtils.isNull(deptPostId)) {
            return Result.builder().success("我的部门不见了");
        }

        QueryWrapper queryWrapper = new QueryWrapper();
        queryWrapper.eq("tmpt_auth_dept_post_id", deptPostId);
        queryWrapper.lt("tmpt_auth_position", position);
        queryWrapper.eq("deleteflag", 0);
        List<TmptAuthUserBiz> subordinateList = tmptAuthUserBizMapper.selectList(queryWrapper);

        List<TmptAuthUserBizNoPsdDto> subordinateDtoList = mapper.maplist(subordinateList, TmptAuthUserBizNoPsdDto.class);
        // 把密码清除了

        return Result.builder(subordinateDtoList).success();
    }


    // ==================================================================================
    // ========== 以下使用的是 Mybatis-plus 实现, 适合单表操作 ==============================
    // ==================================================================================

    /**
    * create a object
    * @param tmptAuthUserBizDto
    * @return
    */
    @Override
    public Result<TmptAuthUserBizDto> create(TmptAuthUserBizDto tmptAuthUserBizDto) {
        //判断登录名是否重复
        List<TmptAuthUserBiz>  authUserBizList = tmptAuthUserBizService.selectListByKey("loginname", tmptAuthUserBizDto.getLoginname());
        if (authUserBizList.size()>0) {
            return Result.builder().fault("系纺已存在登录名："+tmptAuthUserBizDto.getLoginname());
        }

        // dto to entity
        TmptAuthUserBiz tmptAuthUserBiz = mapper.map(tmptAuthUserBizDto, TmptAuthUserBiz.class);
        tmptAuthUserBiz.setPasswordBcrypt(passwordEncoder.encode(tmptAuthUserBizDto.getPasswordBcrypt()));
        tmptAuthUserBiz.insert();

        //bind role
        String roleIds = tmptAuthUserBizDto.getRoleIds();
        if(!StringUtils.isNull(roleIds)) {
            List<String> roleIdStrList = Arrays.asList(roleIds.split(","));
            List<Long> roleIdList = new ArrayList<>();
            for(String roleId: roleIdStrList){
                roleIdList.add(Long.parseLong(roleId));
            }
            this.bindUserAndRole(tmptAuthUserBiz.getId(), roleIdList);
        }

        return Result.builder();
    }

    /**
    * update a object by Id
    * @param tmptAuthUserBizDto
    * @param updateWrapper
    * @return
    */
    @Override
    public Result<TmptAuthUserBizDto> update(TmptAuthUserBizDto tmptAuthUserBizDto, UpdateWrapper updateWrapper) {
        Result<TmptAuthUserBizDto> result = new Result<>();

        //登录无法修改
        tmptAuthUserBizDto.setLoginname(null);

        // dto to entity
        TmptAuthUserBiz tmptAuthUserBiz = mapper.map(tmptAuthUserBizDto, TmptAuthUserBiz.class);
        //密码加密, 重置密码
        if(!StringUtils.isNull(tmptAuthUserBizDto.getPasswordBcrypt())) {
            tmptAuthUserBiz.setPasswordBcrypt(passwordEncoder.encode(tmptAuthUserBizDto.getPasswordBcrypt()));
        }
        tmptAuthUserBizMapper.update(tmptAuthUserBiz, updateWrapper);

        //bind role
        String roleIds = tmptAuthUserBizDto.getRoleIds();
        if(!StringUtils.isNull(roleIds)) {
            List<String> roleIdStrList = Arrays.asList(roleIds.split(","));
            List<Long> roleIdList = new ArrayList<>();
            for(String roleId: roleIdStrList){
                roleIdList.add(Long.parseLong(roleId));
            }
            this.bindUserAndRole(tmptAuthUserBizDto.getId(), roleIdList);
        }

        return result.success();
    }

    private void bindUserAndRole(Long userId, List<Long> roleIdList) {

        //清除原来关系
        TmptAuthUserA2roleList linkParam = new TmptAuthUserA2roleList();
        linkParam.setA2userListId(userId);
        tmptAuthUserA2roleListMapper.delete(new QueryWrapper(linkParam));

        //取角色
        for(Long roleId : roleIdList){
            TmptAuthUserA2roleListBiz link = new TmptAuthUserA2roleListBiz();
            link.setA2userListId(userId);
            link.setA2roleListId(roleId);
            tmptAuthUserA2roleListMapper.insert(link);
        }

    }

    /**
    * 分页 (无合计功能)
    * @param page
    * @param queryWrapper
    * @return
    */
    public Result<TmptAuthUserBizDto> page(Page<TmptAuthUserBiz> page, QueryWrapper<TmptAuthUserBiz> queryWrapper){
        return super.page(page, queryWrapper);
    }

    /**
    * select all by queryWrapper
    * @param queryWrapper
    * @return
    */
    @Override
    public Result<TmptAuthUserBizDto> selectBy(QueryWrapper<TmptAuthUserBiz> queryWrapper) {
        return super.selectBy(queryWrapper);
    }

    /**
    * select one by id
    * @param id
    * @return
    */
    @Override
    public Result<TmptAuthUserBizDto> selectById(Long id) {
        return super.selectById(id);
    }




    // ==================================================================================
    // ========== 以下使用的是自定义的 mapper.xml 实现, 适合多表查询 =========================
    // ==================================================================================

    /**
    * 分页查询：mybatis plus 自定义sql分页查询
    * 默认开启合计查询，按需注掉代码
    * @param page
    * @param queryWrapper
    * @return
    */
    @Override
    public Result<TmptAuthUserBizDto> myPage(Page<TmptAuthUserBiz> page, QueryWrapper<TmptAuthUserBiz> queryWrapper) {
        Result<TmptAuthUserBizDto> result = new Result();

        IPage<TmptAuthUserBiz> iPage = tmptAuthUserBizMapper.myPageHasRolesNoPsd(page, queryWrapper);
        // 查询结果转换成DTO
        List<TmptAuthUserBizDto> tmptAuthUserBizDtoList = mapper.maplist(iPage.getRecords(), TmptAuthUserBizDto.class);
        // 返回结果集
        result.getMap().put("total", iPage.getTotal());
        result.getMap().put("rows", tmptAuthUserBizDtoList);

        // 合计
        List<TmptAuthUserBiz> sumList = tmptAuthUserBizMapper.mySelectSum(queryWrapper);
        List<TmptAuthUserBizDto> sumDtoList = mapper.maplist(sumList, TmptAuthUserBizDto.class);
        result.getMap().put("footer", sumDtoList);

        return result.success();
    }

    @Override
    public Result<TmptAuthUserBizDto> mySelectBy(QueryWrapper<TmptAuthUserBiz> queryWrapper) {
        return super.mySelectBy(queryWrapper);
    }

    @Override
    public Result<TmptAuthUserBizDto> mySelectById(long id) {
        return super.mySelectById(id);
    }

}
